import AgoraRTC from './AgoraRTC_N-4.20.2'
import axios from 'axios'

const APP_ID = '10c8c0e6f164425daaf04632eb32a400'

export default class AgoraRTCClient {
    constructor(emitter, options) {
        this._client = null
        this._joined = false
        this.localAudioTrack = null
        this.localVideoTrack = null
        this._eventBus = emitter
        this._uid = null
        this._subscribed = false
        this._created = false
        this._host = options.isDev
            ? 'remote.test.x431.com/'
            : options.isOversea
                ? 'remotediag.x431.com'
                : 'remote.x431.com'
    }

    static getRtcToken(uid, channel, options) {
        let _host = options.isDev
            ? 'remote.test.x431.com'
            : options.isOversea
                ? 'remotediag.x431.com'
                : 'remote.x431.com'

        return new Promise((resolve, reject) => {
            try {
                axios({
                    url: `${location.protocol}//${_host}/getRtcToken?user_id=${uid}&channel_name=${channel}`,
                    method: 'get',
                }).then(res => {
                    resolve(res.data)
                }).catch(err => reject(err))
            } catch (error) {
                reject(error)
            }
        })
    }

    async createClient({ mode, codec }) {
        AgoraRTC.setLogLevel(2)
        this._client = AgoraRTC.createClient({ mode: mode, codec: codec })
        this._created = true
        this.onMediaDeviceChange()
        return this._client
    }

    clientListener() {
        this._client.on("local-user-published", (localTrack) => {
            this.localAudioTrack = localTrack.audioTrack
            this.localVideoTrack = localTrack.videoTrack
        })

        this._client.on("user-published", async (remoteUser, mediaType) => {
            await this._client.subscribe(remoteUser, mediaType)
            this._subscribed = true
            this._eventBus.emit('subscribed', remoteUser, mediaType)
        })
    }

    async join(options) {
        this._joined = 'pending'
        let tracks = []
        this._uid = await this._client.join(APP_ID, options.channel, options.token, parseInt(options.uid))
        this._joined = true

        this.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack()
        tracks.push(this.localAudioTrack)

        // 视频通话
        if (options.mediaType == 'video') {
            this.localVideoTrack = await AgoraRTC.createCameraVideoTrack()
            tracks.push(this.localVideoTrack)
        }

        await this._client.publish(tracks)

        this._eventBus.emit('local-user-published', {
            audioTrack: this.localAudioTrack,
            videoTrack: this.localVideoTrack
        })
    }

    async leave() {
        if (!this._client) {
            return Promise.resolve()
        }

        if (this.localAudioTrack) {
            this.localAudioTrack.stop()
            this.localAudioTrack.close()
        }

        if (this.localVideoTrack) {
            this.localVideoTrack.stop()
            this.localVideoTrack.close()
        }

        await this._client.leave()
        this._joined = false
        this._created = false
        this._client = null
        return Promise.resolve()
    }

    setRemoteVideoStreamType(uid, streamType) {
        this._client.setRemoteVideoStreamType(uid, streamType)
    }

    async getDevices() {
        return AgoraRTC.getDevices()
    }

    on(event, callback) {
        const customerEvents = [
            'local-user-published',
            'subscribed',
            'microphone-changed',
            'camera-changed',
        ]
        if (customerEvents.includes(event)) {
            this._eventBus.emit(event, callback)
            return
        }
        this._client.on(event, callback)
    }

    onMediaDeviceChange() {
        AgoraRTC.onMicrophoneChanged = async (changedDevice) => {
            if (changedDevice.state === 'ACTIVE') {
                this.localAudioTrack && this.localAudioTrack.setDevice(changedDevice.device.deviceId);
                this._eventBus.emit('microphone-changed', changedDevice.device)
            } else {
                const oldMicrophones = await AgoraRTC.getMicrophones();
                if (oldMicrophones.length > 0) {
                    if (
                        this.localAudioTrack &&
                        changedDevice.device.label === this.localAudioTrack.getTrackLabel()
                    ) {
                        this.localAudioTrack.setDevice(oldMicrophones[0].deviceId);
                    }
                    this._eventBus.emit('microphone-changed', oldMicrophones[0].deviceId);
                } else {
                    this._eventBus.emit('microphone-changed', null);
                }
            }
        }
        AgoraRTC.onCameraChanged = async (changedDevice) => {
            // 插入设备时，切换到新插入的设备。
            if (changedDevice.state === 'ACTIVE') {
                this.localVideoTrack &&
                    this.localVideoTrack.setDevice(changedDevice.device.deviceId);
                this._eventBus.emit('camera-changed', changedDevice.device.deviceId);
            } else {
                // 拔出设备为当前设备时，切换到一个已有的设备。
                const oldCameras = await AgoraRTC.getCameras();
                if (oldCameras.length > 0) {
                    if (
                        this.localVideoTrack &&
                        changedDevice.device.label === this.localVideoTrack.getTrackLabel()
                    ) {
                        this.localVideoTrack.setDevice(oldCameras[0].deviceId);
                    }
                    this._eventBus.emit('camera-changed', oldCameras[0].deviceId);
                } else {
                    this._eventBus.emit('camera-changed', null);
                }
            }
        };

    }

    controlStream(type, bool) {
        //通话中音视频控制
        if (type === "audio") {
            this.localAudioTrack && this.localAudioTrack.setMuted(bool)
        } else {
            this.localVideoTrack && this.localVideoTrack.setEnabled(bool)
        }

    }

    reset() {
        this._client = null
        this._joined = false
        this.localAudioTrack = null
        this.localVideoTrack = null
        this._uid = null
        this._subscribed = false
        this._created = false
    }
}